package com.qingzhuge.controller;

import com.qingzhuge.cache.Constants;
import com.qingzhuge.common.HttpCode;
import com.qingzhuge.common.Resources;
import com.qingzhuge.common.utils.EnumUtil;
import com.qingzhuge.controller.base.AbstractController;
import com.qingzhuge.controller.security.ControllerSecurityBody;
import com.qingzhuge.controller.security.RsaKey;
import com.qingzhuge.dto.response.ResponseBodyDto;
import com.qingzhuge.exception.BaseException;
import com.qingzhuge.exception.TokenException;
import com.qingzhuge.exception.ValidatorException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.annotation.Resource;
import java.util.Map;

/**
 * @author : zero.xiao
 * @description : 异常处理器
 * @date :2018/6/14 0014 下午 16:09
 * @modified :
 * @since : 1.0.0
 */
@RestControllerAdvice
public class SysExceptionHandler extends AbstractController {

    @Resource
    private ControllerSecurityBody controllerSecurityBody;
    /**
     * 处理自定义异常
     */
    @ExceptionHandler(BaseException.class)
    public ResponseEntity<ResponseBodyDto<Object>> handleException(BaseException e) {
        HttpCode code = EnumUtil.getEnumBycode(HttpCode.class, e.getCode());
        String msg = e.getMessage();
        if (StringUtils.isBlank(msg)){
            msg = code.message();
        }
        if (e instanceof ValidatorException){
            log.error("{}",e);
        }else {
            log.debug("{}:{},{}",e.getClass().getSimpleName(),msg,e.getCode());
        }
        return returnSuccess( code.value(), msg, e.getData());
    }

    @ExceptionHandler(TokenException.class)
    public ResponseEntity<ResponseBodyDto<Object>> handleException(TokenException e) {
        log.debug("{}:{},{}",e.getClass().getSimpleName(),e.getMessage(),e.getCode());
        RsaKey rsaKey = controllerSecurityBody.get();
        String publicKey = rsaKey.getPublicKey();
        return returnFailed( e.getCode(), e.getMessage(), publicKey);
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public ResponseEntity<ResponseBodyDto<Object>> handleException(DuplicateKeyException e) {
        log.error("{}",e);
        return returnFailed(Resources.getMessage(Constants.I18n.DATA__EXISTS));
    }

    /**
     * 异常处理
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ResponseBodyDto<Object>> handleException(Exception e) {
        String unauthorizedExceptionName = "org.apache.shiro.authz.UnauthorizedException";
        String unauthenticatedException = "org.apache.shiro.authz.UnauthenticatedException";
        String invalidSessionExceptionName = "org.apache.shiro.session.InvalidSessionException";
        int code;
        String msg;
        Map data = null;
        if (e instanceof BaseException) {
            code = ((BaseException) e).getCode();
            data = ((BaseException) e).getData();
            msg = e.getMessage();
            if (StringUtils.isBlank(msg)){
                msg = HttpCode.VALIDATOR_FAILED.message();
            }
        } else if (e instanceof IllegalArgumentException) {
            code = HttpCode.BAD_REQUEST.value();
            msg = HttpCode.BAD_REQUEST.message();
        } else if (unauthenticatedException.equals(e.getClass().getName())) {
            code = HttpCode.FORBIDDEN.value();
            msg = HttpCode.FORBIDDEN.message();
        } else if (unauthorizedExceptionName.equals(e.getClass().getName())) {
            code = HttpCode.UNAUTHORIZED.value();
            msg = HttpCode.UNAUTHORIZED.message();
        } else if (invalidSessionExceptionName.equals(e.getClass().getName())) {
            code = HttpCode.INTERNAL_SERVER_ERROR.value();
            msg = HttpCode.INTERNAL_SERVER_ERROR.message();
        } else {
            code = HttpCode.INTERNAL_SERVER_ERROR.value();
            msg = e.getMessage();
        }
        String uri = request.getRequestURI();
        log.error("Exception request path:{} {}",uri,e);
        return returnFailed(code, msg, data);
    }
}
